package com.vcc.boss.controller;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckSafe;
import com.vcc.core.annotations.RepeatSubmit;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.NotFoundException;
import com.vcc.core.exception.PermissionException;
import com.vcc.core.exception.ProgramException;
import com.vcc.core.util.RedisCustomizeUtils;
import com.vcc.data.entity.BossRolePermission;
import com.vcc.data.entity.BossUserPermission;
import com.vcc.data.entity.Permission;
import com.vcc.service.boss.request.permission.CreatePermissionDto;
import com.vcc.service.boss.request.permission.SetUserHasPersonalDto;
import com.vcc.service.boss.request.permission.UpdateHasPersonalDto;
import com.vcc.service.boss.response.permission.PermissionVoBoss;
import com.vcc.service.sa.BossUserUtil;
import com.vcc.service.service.*;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("permission")
public class PermissionController {

    @Autowired
    private BossRoleService bossRoleService;
    @Autowired
    private BossRolePermissionService bossRolePermissionService;
    @Autowired
    private BossUserPermissionService bossUserPermissionService;
    @Autowired
    private PermissionService permissionService;

    @Autowired
    private UserService userService;
    @Resource
    private BossUserService bossUserService;

    @RestPack
    @SaCheckLogin
    @GetMapping("listByUserId")
    public List<PermissionVoBoss> listByUserId() {
        //角色权限
        List<BossRolePermission> bossRolePermissions = bossRolePermissionService.listByUserId(BossUserUtil.getId());
        //个人权限
        List<BossUserPermission> bossUserPermissions = bossUserPermissionService.listByUserId(BossUserUtil.getId());
        List<Permission> permissionList = permissionService.list();
        //角色权限+个人权限

        List<PermissionVoBoss> list = bossRolePermissions.stream().map(it -> {
            Permission permission = permissionList.stream().filter(p -> p.getId().equals(it.getPermissionId())).findFirst().orElseThrow(() ->
                    new PermissionException("解析权限发生错误"));
            return new PermissionVoBoss(permission, it.getStatus());
        }).distinct().collect(Collectors.toList());

        for (BossUserPermission bossUserPermission : bossUserPermissions) {
            Permission permission = permissionList.stream().filter(p -> p.getId().equals(bossUserPermission.getPermissionId())).findFirst().orElseThrow(() -> new PermissionException("解析权限发生错误"));
            PermissionVoBoss permissionVo = new PermissionVoBoss(permission, 0);
            if (!list.contains(permissionVo)) {
                list.add(permissionVo);
            }
        }
        return list;
    }

    @RestPack
    @SaCheckLogin
    @SaCheckPermission(value = "admin:permission:user:switch")
    @GetMapping("listBossUserPermission")
    public List<PermissionVoBoss> listBossUserPermission(Long bossUserId) {
        //个人权限
        List<BossUserPermission> bossUserPermissions = bossUserPermissionService.listByUserId(bossUserId);
        if (bossUserPermissions.isEmpty()) {
            return new ArrayList<>();
        }
        List<Permission> permissionList = permissionService.listByIds(
                bossUserPermissions.stream().map(BossUserPermission::getPermissionId).collect(Collectors.toList())
        );
        return permissionList.stream().map(it -> new PermissionVoBoss(it, 0)).distinct().collect(Collectors.toList());
    }


    @RestPack
    @SaCheckLogin
    @SaCheckPermission(value = "admin:permission:list:view")
    @GetMapping("listAll")
    public List<PermissionVoBoss> listAll() {
        List<Permission> permissions = permissionService.listAll();
        RedisCustomizeUtils.removeKey("all_permissions");
        return buildPermissionTreeOptimized(permissions.stream().map(it -> new PermissionVoBoss(it, 0)).toList());
    }


    /**
     * 使用Map优化树构建（O(n)复杂度）
     *
     * @param permissionList 权限列表
     * @return 树状结构的权限列表
     */
    public List<PermissionVoBoss> buildPermissionTreeOptimized(List<PermissionVoBoss> permissionList) {
        if (permissionList == null || permissionList.isEmpty()) {
            return new ArrayList<>();
        }

        // 使用Map存储所有节点，key为节点ID，value为节点对象
        Map<Long, PermissionVoBoss> permissionMap = new HashMap<>();
        List<PermissionVoBoss> rootNodes = new ArrayList<>();

        // 第一次遍历：初始化Map并找到根节点
        for (PermissionVoBoss permission : permissionList) {
            permissionMap.put(permission.getId(), permission);

            // 初始化children列表
            if (permission.getChildren() == null) {
                permission.setChildren(new ArrayList<>());
            }
        }

        // 第二次遍历：建立父子关系
        for (PermissionVoBoss permission : permissionList) {
            Long parentId = permission.getParentId();

            if (parentId == null || parentId == 0) {
                // 根节点
                rootNodes.add(permission);
            } else {
                // 找到父节点并添加到children中
                PermissionVoBoss parent = permissionMap.get(parentId);
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(permission);
                }
            }
        }

        return rootNodes;
    }


    @RestPack
    @SaCheckLogin
    @SaCheckPermission(value = "admin:permission:list:create")
    @PostMapping("create")
    public Boolean createPermission(@RequestBody @Validated CreatePermissionDto createPermissionDto) {
        if (createPermissionDto.getParentId() != null) {
            Permission permission = permissionService.getById(createPermissionDto.getParentId());
            if (permission == null) {
                throw new PermissionException("父权限不存在");
            }
        }
        if (permissionService.existsByCode(createPermissionDto.getCode())) {
            throw new PermissionException("权限编码已存在");
        }
        Permission permission = new Permission();
        permission.setName(createPermissionDto.getName());
        permission.setCode(createPermissionDto.getCode());
        permission.setHasPersonal(createPermissionDto.getHasPersonal());
        permission.setLevelNumber(createPermissionDto.getLevelNumber());
        permission.setParentId(createPermissionDto.getParentId() != null ? createPermissionDto.getParentId() : 0L);
        boolean save = permissionService.save(permission);
        if (save) {
            RedisCustomizeUtils.removeKey("all_permissions");
        }
        return save;
    }


    @RestPack
    @SaCheckLogin
    @RepeatSubmit
    @SaCheckPermission(value = "admin:permission:switch")
    @PostMapping("updateHasPersonal")
    public Boolean updateHasPersonal(@RequestBody @Validated UpdateHasPersonalDto updateHasPersonalDto) {
        Permission permission = permissionService.getById(updateHasPersonalDto.getId());
        if (permission == null) {
            throw new PermissionException("权限不存在");
        }
        return permissionService.updateHasPersonalById(updateHasPersonalDto.getId(), updateHasPersonalDto.getHasPersonal());
    }

    @RestPack
    @SaCheckLogin
    @RepeatSubmit
    @SaCheckPermission(value = "admin:permission:user:switch")
    @PostMapping("setUserSwitch")
    @SaCheckSafe("SET_USER_SWITCH")
    public Boolean setUserSwitch(@RequestBody @Validated SetUserHasPersonalDto setUserHasPersonalDto) {
        List<Permission> permissions = permissionService.listByIds(setUserHasPersonalDto.getPermissionIds());
        if (permissions.size() != setUserHasPersonalDto.getPermissionIds().size()) {
            throw new NotFoundException("部分权限不存在");
        }
        long count = permissions.stream().filter(it -> !it.getHasPersonal()).count();
        if (count > 0) {
            throw new ProgramException("所选权限中包含非个人权限，无法分配给用户");
        }
        if (!bossUserService.existsById(setUserHasPersonalDto.getBossUserId())) {
            throw new NotFoundException("用户不存在");
        }
        bossUserPermissionService.removeByUserId(setUserHasPersonalDto.getBossUserId());
        Set<Long> permissionIdSet = new HashSet<>();
        for (Permission permission : permissions) {
            if (permission.getParentId() == null || permission.getParentId() == 0L) {
                permissionIdSet.addAll(permissionService.listIdParentId(permission.getId()));
            } else {
                permissionIdSet.add(permission.getId());
            }
        }
        List<BossUserPermission> bossUserPermissions = permissionIdSet.stream().map(it -> {
            BossUserPermission bossUserPermission = new BossUserPermission();
            bossUserPermission.setBossUserId(setUserHasPersonalDto.getBossUserId());
            bossUserPermission.setPermissionId(it);
            bossUserPermission.setStatus(true);
            return bossUserPermission;
        }).collect(Collectors.toList());
        bossUserPermissionService.saveBatch(bossUserPermissions);
        RedisCustomizeUtils.removeKey("user_user_permission:" + setUserHasPersonalDto.getBossUserId());
        RedisCustomizeUtils.removeKey("all_permissions");
        return true;
    }
}
